using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using Aurora.HttpClient;
using Gateway.Common.Extensions;
using Gateway.Common.Utils;
using Gateway.IQuery.SystemSetting;
using Gateway.IQuery.SystemSetting.Result;
using Gateway.IRepositories;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;

namespace Gateway.Query;

/// <summary>
/// 
/// </summary>
public class SystemSettingQuery : ISystemSettingQuery
{
    private readonly IQueryRepository _repository;
    private readonly IHttpClient _httpClient;
    private readonly IHostEnvironment _environment;
    private readonly IHttpContextAccessor _contextAccessor;
    private readonly ILogger<SystemSettingQuery> _logger;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="repository"></param>
    /// <param name="httpClient"></param>
    /// <param name="environment"></param>
    /// <param name="contextAccessor"></param>
    /// <param name="logger"></param>
    public SystemSettingQuery(IQueryRepository repository, IHttpClient httpClient, IHostEnvironment environment, IHttpContextAccessor contextAccessor, ILogger<SystemSettingQuery> logger)
    {
        _repository = repository;
        _httpClient = httpClient;
        _environment = environment;
        _contextAccessor = contextAccessor;
        _logger = logger;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public async Task<SystemSettingDetailResult> GetDetail()
    {
        //查询系统配置
        var system = await _repository.FindAsync<SystemSettingDetailResult>(_ => true);
        if (system == null)
            return new SystemSettingDetailResult();
        var sms = await _repository.FindAsync<SystemSmsDetailResult>(_ => true);
        var t = system.LoginType.Equals("user") || system.LoginType.Equals("all");
        if (sms != null)
        {
            system.Sms = sms;
        }

        var extensionCode = await _repository.GetListAsync<SystemExtensionSettingDetailResult>(_ => true);
        system.Extensions = extensionCode;
        return system;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public async Task<SystemServerResult> GetServerInfo()
    {
        IpCnResp ipInfo = await GetIpAndAddress();
      
        return new SystemServerResult()
        {
            HostName = Environment.MachineName,
            SystemOs = ComputerUtil.GetOsInfo(),
            OsArchitecture = Environment.OSVersion.Platform.ToString() + " " +
                             RuntimeInformation.OSArchitecture.ToString(),
            ProcessorCount = Environment.ProcessorCount + " 核",
            SysRunTime = ComputerUtil.GetRunTime(),
            RemoteIp = ipInfo != null ? (ipInfo.Ip + " " + ipInfo.Address) : "",
            LocalIp =_contextAccessor?.HttpContext?.Connection?.LocalIpAddress?.ToString()??"",
            FrameworkDescription = RuntimeInformation.FrameworkDescription,
            Environment = _environment.IsDevelopment()? "Development" : "Production",
            Wwwroot = _environment.ContentRootPath,
            Stage = _environment.IsStaging()?"Stage环境" : "非Stage环境"
        };
    }

    /// <summary>
    /// 获取网络ip和地址
    /// </summary>
    /// <returns></returns>
    private async Task<IpCnResp> GetIpAndAddress()
    {
        IpCnResp ipInfo = null;
        try
        {
            var header = new Dictionary<string, string>()
            {
                {
                    "User-Agent",
                    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62"
                }
            };
            string ip = await _httpClient.GetAsync<string>("https://api64.ipify.org/");
            ip = ip?.Trim()??"";
            if (!string.IsNullOrEmpty(ip))
            {
                ipInfo = new IpCnResp();
                var geoResponse = await _httpClient.GetAsync<string>($"http://ip-api.com/json/{ip}?lang=zh-CN");
                var geoInfo = JObject.Parse(geoResponse);
                ipInfo.Address = geoInfo["country"] + " " + geoInfo["regionName"] + " " + geoInfo["city"];
                ipInfo.Ip = ip;
            }
        }
        catch (Exception e)
        {
            _logger.LogError(e,"获取网络ip异常");
        }

        return ipInfo;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public Task<SystemServerUsedResult> GetServerUsed()
    {
        var programStartTime = Process.GetCurrentProcess().StartTime;
        var totalMilliseconds = (DateTime.Now - programStartTime).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
        var ts = totalMilliseconds.Contains('.') ? totalMilliseconds.Split('.')[0] : totalMilliseconds;
        var programRunTime = StringExtensions.FormatTime(ts.ParseToLong());
        var memoryMetrics = ComputerUtil.GetComputerInfo();
        
        
        return Task.FromResult(new SystemServerUsedResult()
        {
            FreeRam=  memoryMetrics.FreeRam, // 空闲内存
            UsedRam=   memoryMetrics.UsedRam, // 已用内存
            TotalRam= memoryMetrics.TotalRam, // 总内存
            RamRate= memoryMetrics.RamRate, // 内存使用率
            CpuRate= memoryMetrics.CpuRate, // Cpu使用率
            StartTime = programStartTime.ToString("yyyy-MM-dd HH:mm:ss"), // 服务启动时间
            RunTime = programRunTime, // 服务运行时间
        });
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public Task<List<SystemDiskResult>> GetDiskInfoAsync()
    {
        var diskInfos = ComputerUtil.GetDiskInfos();
        return Task.FromResult(diskInfos.Select((diskInfo => new SystemDiskResult()
        {
            DiskName = diskInfo.DiskName,
            TypeName = diskInfo.TypeName,
            TotalFree = diskInfo.TotalFree,
            TotalSize = diskInfo.TotalSize,
            Used = diskInfo.Used,
            AvailableFreeSpace = diskInfo.AvailableFreeSpace,
            AvailablePercent = diskInfo.AvailablePercent
        })).ToList());
    }
}